<?php

namespace app\uniapp\service;

use app\model\delivery\PostageTemplate;
use app\uniapp\service\traits\InstanceTrait;
use think\db\Query;

class PostageTemplateService extends UniBaseService
{

    use InstanceTrait;

    function initialize()
    {
        $this->model = new PostageTemplate();
    }

    function formatData(array $data): array
    {
        return $data;
    }

    /**
     * 重新查询函数
     * @return Query
     */
    public function query(): Query
    {
        return $this->makeQuery()->filter(function ($v) {
            // 地区邮费
            $v->regions = PostageTemplateRegionService::instance()->setWhere([
                ['tpl_id', '=', $v->id]
            ])->select();
            // 条件邮费
            $v->conditions = PostageTemplateRegionConditionService::instance()->setWhere([
                ['tpl_id', '=', $v->id]
            ])->select();
            // 不包邮地区
            $v->regionsNo = PostageTemplateRegionNoService::instance()->setWhere([
                ['tpl_id', '=', $v->id]
            ])->find();

        });
    }




    /**
     * 指定的收货地址是否支持快递发货
     * @param $postageTpl // 运费模板
     * @param $userAddress  // 收货地址
     * @return bool
     */
    function isExpressDelivery($postageTpl, $userAddress): bool
    {
        $tplType = $postageTpl->tpl_type;
        $flag = true;
        if ($tplType == 'custom' && $userAddress){
            // 不包邮地区验证
            if ($postageTpl->regionsNo){
                $noIdArr = $postageTpl->regionsNo->regionIdArr;    // 不配送地区的id列表
                if (in_array($userAddress['province_id'], $noIdArr)){   // 整个省都不配送
                    $flag = false;
                }elseif (in_array($userAddress['city_id'], $noIdArr)){  // 整个市不配送
                    $flag = false;
                }elseif (in_array($userAddress['district_id'], $noIdArr)){  // 区县不配送
                    $flag = false;
                }
            }
        }

        return $flag;
    }

    /**
     * 是否满足按照条件包邮
     * @param $tpl
     * @param $userAddress
     * @param $price
     * @param $num
     * @param $weight
     * @param $volume
     * @return bool|void
     */
    public function isConditionExpress($tpl, $userAddress, $price, $num, $weight, $volume){
        $isCondition = false;   // 默认为不满足按条件包邮
        if ($tpl->tpl_type=='custom' && $tpl->conditions){  // 按条件包邮
            $costType = $tpl->cost_type;    // 运费计算方式
            $size = 0; // 将件数、数量、体积都转换成size
            if ($costType == 1){    // 按件数
                $size = $num;
            }elseif ($costType == 2) {    // 按重量
                $size = $weight;
            }elseif ($costType == 3){   // 按体积
                $size = $volume;
            }

            foreach ($tpl->conditions as $k=>$con){
                $flag = false;
                $conIdArr = miExplode($con->region_ids);
                if (in_array($userAddress['province_id'], $conIdArr)){   // 整个省
                    $flag = true;
                }elseif (in_array($userAddress['city_id'], $conIdArr)){  // 整个市
                    $flag = true;
                }elseif (in_array($userAddress['district_id'], $conIdArr)){  // 区县
                    $flag = true;
                }
                if ($flag){ // 符合按条件包邮地区，设置运费金额，并且退出循环
                    // 验证包邮条件
                    if ($price>=$con->price && $size>=$con->piece){ // 包邮
                        $isCondition = true;
                    }
                    break;
                }
            }

            return $isCondition;

        }
    }

    /**
     * 区域运费规则，有则返回所属规则，没有则返回false
     * @param $tpl
     * @param $userAddress
     * @return false|mixed|void
     */
    public function expressRegion($tpl, $userAddress){
        if ($tpl->tpl_type=='custom' && $tpl->regions){  // 按条件包邮
            foreach ($tpl->regions as $v){
                $conIdArr = $v->regionIdArr;
                if (in_array($userAddress['province_id'], $conIdArr)){   // 整个省
                    return $v;
                }elseif (in_array($userAddress['city_id'], $conIdArr)){  // 整个市
                    return $v;
                }elseif (in_array($userAddress['district_id'], $conIdArr)){  // 区县
                    return $v;
                }
            }

            return false;

        }
    }


    /**
     * 计算运费
     * @param $tpl
     * @param $userAddress
     * @param $price
     * @param $num
     * @param $weight
     * @param $volume
     * @return float|int
     */
    public function getExpressPrice($tpl, $userAddress, $price, $num, $weight, $volume): float|int
    {
        $postagePrice = 0;  // 声明运费金额
        $tplType = $tpl->tpl_type;  // 运费模板类型
        $costType = $tpl->cost_type;    // 运费计算方式
        if ($tplType == 'custom'){    // 自定义包邮
            $isExpressDelivery = PostageTemplateService::instance()->isExpressDelivery($tpl, $userAddress);
            if (!$isExpressDelivery){   // 不支持快递发货
                return 0;
            }

            $size = 0; // 将件数、数量、体积都转换成size
            if ($costType == 1){    // 按件数
                $size = $num;
            }elseif ($costType == 2) {    // 按重量
                $size = $weight;
            }elseif ($costType == 3){   // 按体积
                $size = $volume;
            }
            // 是否满足按条件包邮
            $isConditionExpress = PostageTemplateService::instance()->isConditionExpress($tpl,$userAddress, $price, $num, $weight, $volume);
            if ($isConditionExpress) { // 不满足包邮条件
                return 0;
            }

            // 是否属于指定区域运费
            $expressRegion = PostageTemplateService::instance()->expressRegion($tpl, $userAddress);
            if ($expressRegion){  // 按照指定区域规则计算运费
                $computeData = $expressRegion;  // 计算运费需要的数据
            }else{
                $computeData = $tpl;
            }

            // 计算运费
            if ($size <= $computeData->first_piece){ // 数量不超过首件数量
                $postagePrice = $computeData->first_price;
            }else{
                // 按照续件规则计算
                $postagePrice = $computeData->first_price + ceil(($size - $computeData->first_piece)/$computeData->continue_piece )*$computeData->continue_price;
            }


        }elseif ($tplType == 'fixed'){  // 固定运费
            $postagePrice = $tpl->fixed_price;
        }

        return $postagePrice;

    }

}
